home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
CUGUK
/
COMMS
/
C101.ZIP
/
UUPC11XS.ZIP
/
UUCICO
/
DCPFPKT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-20
|
17KB
|
500 lines
/*--------------------------------------------------------------------*/
/* Flow control ("f") protocol. */
/* */
/* This protocol relies on flow control of the data stream. It */
/* is meant for working over links that can (almost) be */
/* guaranteed to be errorfree, specifically X.25/PAD links. A */
/* sumcheck is carried out over a whole file only. If a */
/* transport fails the receiver can request retransmission(s). */
/* This protocol uses a 7-bit datapath only, so it can be used */
/* on links that are not 8-bit transparent. */
/* */
/* When using this protocol with an X.25 PAD: Although this */
/* protocol uses no control chars except CR, control chars NULL */
/* and ^P are used before this protocol is started; since ^P is */
/* the default char for accessing PAD X.28 command mode, be */
/* sure to disable that access (PAD par 1). Also make sure */
/* both flow control pars (5 and 12) are set. The CR used in */
/* this proto is meant to trigger packet transmission, hence */
/* par 3 should be set to 2; a good value for the Idle Timer */
/* (par 4) is 10. All other pars should be set to 0. */
/* */
/* Normally a calling site will take care of setting the local */
/* PAD pars via an X.28 command and those of the remote PAD via */
/* an X.29 command, unless the remote site has a special */
/* channel assigned for this protocol with the proper par */
/* settings. */
/* */
/* Author: Piet Beertema, CWI, Amsterdam, Sep 1984 */
/* */
/* Adapted to uupc 3.0 and THINK C 4.0 by Dave Platt, Jul 1991 */
/*--------------------------------------------------------------------*/
/*
* $Id: DCPFPKT.C 1.5 1992/11/20 12:38:26 ahd Exp $
*
* $Log: DCPFPKT.C $
* Revision 1.5 1992/11/20 12:38:26 ahd
* Drop rcsid
*
* Revision 1.4 1992/11/19 03:01:13 ahd
* drop rcsid
*
* Revision 1.3 1992/11/19 02:36:29 ahd
* Revision 1.2 1992/11/15 20:10:47 ahd
* Clean up modem file support for different protocols
*
*/
/*--------------------------------------------------------------------*/
/* System include files */
/*--------------------------------------------------------------------*/
#include <stdio.h>
#include <time.h>
#include <string.h>
/*--------------------------------------------------------------------*/
/* UUPC/extended include files */
/*--------------------------------------------------------------------*/
#include "lib.h"
#include "dcp.h"
#include "dcpfpkt.h"
#include "dcpsys.h"
#include "hostable.h"
#include "security.h"
#include "ssleep.h"
#include "modem.h"
#include "ulib.h"
/*--------------------------------------------------------------------*/
/* Defines */
/*--------------------------------------------------------------------*/
#ifndef MAXMSGLEN
#define MAXMSGLEN BUFSIZ
#endif MAXMSGLEN
currentfile();
/*--------------------------------------------------------------------*/
/* Internal function prototypes */
/*--------------------------------------------------------------------*/
static int fsendresp(int state);
/*--------------------------------------------------------------------*/
/* Global variables */
/*--------------------------------------------------------------------*/
static int chksum;
/*--------------------------------------------------------------------*/
/* f o p e n p k */
/* */
/* Open "f" protocol to other system */
/*--------------------------------------------------------------------*/
int fopenpk(const boolean master)
{
flowcontrol(TRUE);
if ( M_fPacketSize > MAXPACK)
M_fPacketSize = MAXPACK;
pktsize = M_fPacketSize;
ssleep(2); /* Give peer time to perform corresponding port setup */
return OK;
} /* fopenpk */
/*--------------------------------------------------------------------*/
/* f c l o s e p k */
/* */
/* Shutdown "f" procotol with other system */
/*--------------------------------------------------------------------*/
fclosepk()
{
flowcontrol(FALSE);
return OK;
} /* fclosepk */
/*--------------------------------------------------------------------*/
/* f w r m s g */
/* */
/* Send a control message to remote system with "f" procotol */
/*--------------------------------------------------------------------*/
int fwrmsg(char *str)
{
char bufr[MAXMSGLEN];
char *s = bufr;
while (*str)
*s++ = *str++;
if (*(s-1) == '\n')
s--;
*s++ = '\r';
if (swrite(bufr, s - bufr) == (s - bufr))
return OK;
else
return FAILED;
} /* fwrmsg */
/*--------------------------------------------------------------------*/
/* f r d m s g */
/* */
/* Read a control message from remote host with "f" protocol */
/*--------------------------------------------------------------------*/
int frdmsg(char *str)
{
char *smax;
char *s = str;
smax = s + MAXPACK - 1;
for (;;) {
if (sread(s, 1, M_fPacketTimeout) <= 0)
{
printmsg(0,"frdmsg: timeout reading message");
*s++ = '\0';
goto msgerr;
}
if (*s == '\r')
break;
if (*s < ' ')
continue;
if (s++ >= smax)
{
printmsg(0,"frdmsg: buffer overflow");
*--s = '\0';
goto msgerr;
} /* if (s++ >= smax) */
}
*s = '\0';
return OK;
msgerr:
printmsg(0,"frdmsg: Message received \"%s\"", str);
return FAILED;
} /* frdmsg */
/*--------------------------------------------------------------------*/
/* f g e t p k t */
/* */
/* Receive an "f" protocol packet of data from the other system */
/*--------------------------------------------------------------------*/
int fgetpkt(char *packet, int *bytes)
{
char *op, c, *ip;
int sum, len, left;
char buf[5], tbuf[1];
int i;
static char special = 0;
static boolean eof = FALSE;
/*--------------------------------------------------------------------*/
/* Handle EOF on previous call */
/*--------------------------------------------------------------------*/
if ( eof )
{
eof = FALSE;
printmsg(0,"fgetpkt: EOF from other host");
*bytes = 0;
if (fsendresp(OK) == OK)
return OK;
else
return FAILED;
} /* if ( eof ) */
left = pktsize;
op = packet;
sum = chksum;
/*--------------------------------------------------------------------*/
/* Loop to fill up one packet */
/*--------------------------------------------------------------------*/
do {
ip = tbuf;
len = sread(ip, 1, M_fPacketTimeout); /* single-byte reads for now */
if (len == 0) {
printmsg(0,"fgetpkt: Timeout after %d seconds", M_fPacketTimeout);
return FAILED; /* Fail if timed out */
}
if ((*ip &= 0177) >= '\172') {
if (special) {
special = 0;
if (*ip++ != '\176')
{
printmsg(0,"fgetpkt: Did not expect character ^%c (x%02x)",
(char) (*(ip-1) + 'A') , (int) *(ip-1));
goto dcorr;
}
len = 0;
while (len < 5) {
i = sread(&buf[len], 5 - len, M_fPacketTimeout);
if (i == 0) {
printmsg(0,
"fgetpkt: Timeout reading %d chars after %d seconds",
5 - len, M_fPacketTimeout);
goto dcorr;
}
len += i;
}
printmsg(6, "fgetpkt: buf=|%.*s|", len , packet);
if (buf[4] != '\r')
{
printmsg(0,
"fgetpkt: error: Expected carriage return, "
"not %s%c (x%02x)",
(buf[4] < ' ') ? "^" : "" ,
(char) (buf[4] + ((buf[4] < ' ') ? 'A' : 0)),
(int) buf[4]);
goto dcorr;
}
sscanf(buf, "%4x", &chksum);
*bytes = op - packet;
if (chksum == sum) {
eof = TRUE;
printmsg(6, "fgetpkt: data=|%.*s|", *bytes , packet);
return OK;
} else {
printmsg(0, "fgetpkt: Checksum mismatch, told %04x, calc %04x",
chksum, sum);
fsendresp(RETRY);
return RETRY;
}
}
special = *ip++;
} else {
if (*ip < '\040') {
printmsg(0,"fgetpkt: error: got control character ^%c (%x)",
(char) (*ip + 'A') , (int) *ip);
goto dcorr;
}
switch (special) {
case 0:
c = (char) (*ip++);
break;
case '\172':
c = (char) (*ip++ - 0100);
break;
case '\173':
c = (char) (*ip++ + 0100);
break;
case '\174':
c = (char) (*ip++ + 0100);
break;
case '\175':
c = (char) (*ip++ + 0200);
break;
case '\176':
c = (char) (*ip++ + 0300);
break;
default:
printmsg(0,"fgetpkt: Invalid special chracter 0x%2x",
(int) special );
panic();
c = '\0';
}
*op++ = c;
left --;
if (sum & 0x8000) {
sum <<= 1;
sum++;
} else
sum <<= 1;
sum += c & 0377;
sum &= 0xffff;
special = 0;
}
} while (left > 0);
/*--------------------------------------------------------------------*/
/* The packet is full of data, return to caller */
/*--------------------------------------------------------------------*/
*bytes = pktsize;
printmsg(6, "fgetpkt: data=|%.*s|", *bytes , packet);
chksum = sum;
return OK;
/*--------------------------------------------------------------------*/
/* The data is corrupt; flush the incoming file */
/*--------------------------------------------------------------------*/
dcorr:
printmsg (0, "Data corrupted, skipping to EOF");
len = 1;
while (len)
len = sread(packet, 1, M_fPacketTimeout);
fsendresp(RETRY);
return RETRY;
} /* fgetpkt */
/*--------------------------------------------------------------------*/
/* f s e n d p k t */
/* */
/* Send an "f" protocol packet to the other system */
/*--------------------------------------------------------------------*/
fsendpkt(char *ip, int len)
{
char *op;
int sum, nl;
int ret;
char obuf[MAXPACK * 2];
op = obuf;
nl = 0;
sum = chksum;
if (len == 0)
{
printmsg(0,"fsendpkt: Internal error: zero length for packet");
return FAILED;
}
do {
if (sum & 0x8000) {
sum <<= 1;
sum++;
} else
sum <<= 1;
sum += *ip & 0377;
sum &= 0xffff;
if (*ip & 0200) {
*ip &= 0177;
if (*ip < 040) {
*op++ = '\174';
*op++ = (char) (*ip++ + 0100);
} else
if (*ip <= 0171) {
*op++ = '\175';
*op++ = *ip++;
}
else {
*op++ = '\176';
*op++ = (char) (*ip++ - 0100);
}
nl += 2;
} else {
if (*ip < 040) {
*op++ = '\172';
*op++ = (char) (*ip++ + 0100);
nl += 2;
} else
if (*ip <= 0171) {
*op++ = *ip++;
nl++;
} else {
*op++ = '\173';
*op++ = (char) (*ip++ - 0100);
nl += 2;
}
}
} while (--len > 0);
chksum = sum;
ret = swrite(obuf, nl);
if ( ret == nl )
return OK;
else
return FAILED;
} /* fsendpkt */
/*--------------------------------------------------------------------*/
/* f f i l e p k t */
/* */
/* Prepare for processing an "f" procotol file transfer */
/*--------------------------------------------------------------------*/
int ffilepkt( void)
{
chksum = 0xffff;
printmsg(3,"ffilepkt: Checksum reset");
return OK;
} /* ffilepkt */
/*--------------------------------------------------------------------*/
/* f e o f */
/* */
/* Transmit "f" protocol end of file to the other system */
/*--------------------------------------------------------------------*/
int feofpkt( void )
{
char ibuf[MAXMSGLEN];
/*--------------------------------------------------------------------*/
/* Transmit EOF with an attached checksum */
/*--------------------------------------------------------------------*/
printmsg(0,"feofpkt: sending EOF");
sprintf(ibuf, "\176\176%04x", chksum);
printmsg(2,"--> %s", ibuf);
fwrmsg(ibuf);
/*--------------------------------------------------------------------*/
/* Now get the response and report it */
/*--------------------------------------------------------------------*/
if (frdmsg(ibuf) == FAILED)
return FAILED;
printmsg(2,"<-- %s",ibuf);
/*--------------------------------------------------------------------*/
/* Determine our next step from the result */
/*--------------------------------------------------------------------*/
switch(*ibuf)
{
case 'R':
return RETRY;
case 'G':
return OK;
default:
return FAILED;
} /* switch */
} /* feofpkt */
/*--------------------------------------------------------------------*/
/* f s e n d r e s p */
/* */
/* Send result to a file transfer to other host */
/*--------------------------------------------------------------------*/
static int fsendresp(int state)
{
char *s;
switch (state)
{
case OK:
s = "G";
break;
case RETRY:
s = "R";
break;
default:
s = "Q";
break;
}
printmsg(2,"--> %s", s);
return fwrmsg(s);
} /* fsendresp */